import threading
import wx
from socket import socket, AF_INET, SOCK_STREAM
import time

class Server(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, id=1002, title='服务器端', size=(400, 450))
        pl = wx.Panel(self)
        box = wx.BoxSizer(wx.VERTICAL)
        fgz1 = wx.FlexGridSizer(wx.HORIZONTAL)

        start_btn = wx.Button(pl, label='启动服务', size=(100, 40))
        record_btn = wx.Button(pl, label='保存聊天', size=(100, 40))
        stop_btn = wx.Button(pl, label='断开服务', size=(100, 40))

        fgz1.Add(start_btn, 1, wx.TOP | wx.LEFT)
        fgz1.Add(record_btn, 1, wx.TOP | wx.CENTER)
        fgz1.Add(stop_btn, 1, wx.TOP | wx.RIGHT)
        box.Add(fgz1, 1, wx.ALIGN_CENTER)

        self.show_text = wx.TextCtrl(pl, size=(400, 410), style=wx.TE_MULTILINE | wx.TE_READONLY)
        box.Add(self.show_text, 1, wx.EXPAND | wx.ALL)

        pl.SetSizer(box)

        '''以上代码为界面绘制'''

        self.isOn = False
        self.host_port = ('', 8888)
        self.server_socket = socket(AF_INET, SOCK_STREAM)
        self.server_socket.bind(self.host_port)
        self.server_socket.listen(5)

        self.session_thread_dict = {}

        '''以下代码为事件绑定'''
        self.Bind(wx.EVT_BUTTON, self.start_server, start_btn)
        self.Bind(wx.EVT_BUTTON, self.stop_server, stop_btn)
        self.Bind(wx.EVT_BUTTON, self.save_record, record_btn)

    def stop_server(self, event):
        self.isOn = False

    def save_record(self, event):
        record = self.show_text.GetValue()
        if record:
            with open('record.log', 'w', encoding='utf-8') as f:
                f.write(record)

    def start_server(self, event):
        if not self.isOn:
            self.isOn = True
            main_thread = threading.Thread(target=self.do_work)
            main_thread.deamon = True
            main_thread.start()

    def do_work(self):
        while self.isOn:
            session_socket, client_addr = self.server_socket.accept()
            user_name = session_socket.recv(1024).decode('utf-8')
            session_thread = SessionThread(session_socket, user_name, self)
            self.session_thread_dict[user_name] = session_thread
            session_thread.start()
            print('--->', user_name)
            self.show_info_and_send_client('服务器', f'{user_name}上线了。', time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
        self.server_socket.close()

    def show_info_and_send_client(self, data_source, data, date_time):
        send_data = f'{data_source}：{data}\n时间：{date_time}'
        self.show_text.AppendText('-'* 40 + '\n' + send_data + '\n')
        for client in self.session_thread_dict.values():
            if client.isOn:
                client.client_socket.send(send_data.encode('utf-8'))

class SessionThread(threading.Thread):
    def __init__(self, client_socket, user_name, server):
        threading.Thread.__init__(self)
        self.client_socket = client_socket
        self.user_name = user_name
        self.server = server
        self.isOn = True

    def run(self):
        print(f'{self.user_name}上线了，开始聊天。已经和服务器连接成功。')
        while self.isOn:
            data = self.client_socket.recv(1024).decode('utf-8')
            if data == 'exit':
                self.server.show_info_and_send_client('服务器通知', f'{self.user_name}离开了',
                                                      time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
                self.isOn = False
            else:
                self.server.show_info_and_send_client(self.user_name, data,
                                                      time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
        self.client_socket.close()



if __name__ == '__main__':
    app = wx.App()
    server = Server()

    server.Show()
    app.MainLoop()

